package httpClient

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"github.com/cihub/seelog"
	"golang.org/x/net/http2"
	"io/ioutil"
	"net"
	"net/http"
	"time"
)

var TransportV2 *http2.Transport
var Transport *http.Transport

type HttpClient struct {
	http.Client
}

type Http2Client struct {
	http.Client
}

func init() {
	TransportV2 = &http2.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // 不校验服务端证书
		AllowHTTP:       true,
		DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
			return net.Dial(network, addr)
		},
	}
	Transport = &http.Transport{
		TLSClientConfig:     &tls.Config{InsecureSkipVerify: true}, // 不校验服务端证书
		MaxIdleConns:        2000,
		MaxIdleConnsPerHost: 200,
		IdleConnTimeout:     time.Duration(10) * time.Second, // 连接空闲超时
	}
}

func (cli *HttpClient) SendRequest(method, url string, data, resultData any) (any, error) {
	jsonData, err := json.Marshal(data)
	if err != nil {
		seelog.Error("decode data error: ", err)
		return nil, err
	}
	req, err := http.NewRequest(method, url, bytes.NewReader(jsonData))
	if err != nil {
		seelog.Error("new request error: ", err)
		return nil, err
	}
	resp, err := cli.DoRequest(req)
	if err != nil {
		seelog.Error("new request error: ", err)
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode == http.StatusOK {
		body, _ := ioutil.ReadAll(resp.Body)
		err = json.Unmarshal(body, &resultData)
		if err != nil {
			seelog.Error("decode response data error: ", err)
			return nil, err
		}
	}
	return resultData, nil
}

func (cli *Http2Client) SendRequest(method, url string, data, resultData any) (any, error) {
	jsonData, err := json.Marshal(data)
	if err != nil {
		seelog.Error("decode data error: ", err)
		return nil, err
	}
	req, err := http.NewRequest(method, url, bytes.NewReader(jsonData))
	if err != nil {
		seelog.Error("new request error: ", err)
		return nil, err
	}
	resp, err := cli.DoRequest(req)
	if err != nil {
		seelog.Error("new request error: ", err)
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode == http.StatusOK {
		body, _ := ioutil.ReadAll(resp.Body)
		err = json.Unmarshal(body, &resultData)
		if err != nil {
			seelog.Error("decode response data error: ", err)
			return nil, err
		}
	}
	return resultData, nil

}

func (cli *HttpClient) DoRequest(req *http.Request) (resp *http.Response, err error) {
	resp, err = cli.Do(req)
	if err != nil {
		seelog.Errorf("http1 request Failed!\nmethod: %s\nurl: %s", req.Method, req.URL.RequestURI())
	}
	return resp, err
}

func (cli *Http2Client) DoRequest(req *http.Request) (resp *http.Response, err error) {
	resp, err = cli.Do(req)
	if err != nil {
		seelog.Errorf("http2 request Failed! err:%s\n", err)
	}
	return resp, err
}

func NewHttpClient() *HttpClient {
	return &HttpClient{
		http.Client{
			Transport: Transport,
			Timeout:   time.Duration(10) * time.Second,
		},
	}
}

func NewHttp2Client() (client *Http2Client) {
	client = &Http2Client{
		http.Client{
			Transport: TransportV2,
			Timeout:   time.Duration(10) * time.Second,
		},
	}
	return client
}
